﻿using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.JSInterop;
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using TrackSystem.Contracts;
using TrackSystem.Entities.Dtos.Equip;
using TrackSystem.Entities.Dtos.Logic;
using TrackSystem.Entities.RequestFeatures;
using Console = System.Console;


namespace TrackSystem.UI.Server.Pages.Configuration
{
    public partial class LogicDefTable
    {
        private IEnumerable<LogicDto> logicDtos = [];
        private ConcurrentDictionary<int, bool> dictChanges = new();
        private string sMsg = "";
        private HubConnection hubConnection;
        private bool bInsertFlag = false;
        private LogicDto addedLogic;
        private IEnumerable<SelectedItem> equipList = [];
        private IEnumerable<SelectedItem> NameItems = [];

        // Page Parameter
        private RequestParameter pageParms = new RequestParameter();
        private int MaxPageNumber = 1;

        private static readonly IEnumerable<SelectedItem> PageItemsSource =
            [
                new("2", "2条/页"),
                new("4", "4条/页"),
                new("10", "10条/页"),
                new("20", "20条/页")
            ];

        private int PageItems { get; set; } = 4;
        private string PageInfoText => $"每页 {PageItems} 条 共 {MaxPageNumber} 页";

        [Inject]
        [NotNull]
        private ToastService? ToastService { get; set; }

        /// <summary>
        /// 初始化函数
        /// </summary>
        /// <param name="firstRender"></param>
        /// <returns></returns>
        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (!firstRender)
                return;

            pageParms = new RequestParameter
            {
                PageNumber = 1,
                PageSize = PageItems,
                QueryString = ""
            };
            // 获取所有逻辑表达式
            await SignalServer(pageParms);

            // 获取所有变量名称
            try
            {
                hubConnection.On<List<string>>("RecvVarNames", (result) =>
                {
                    NameItems = result.Select(c => new SelectedItem(c, c)).ToList();

                    sMsg = $"{DateTime.Now} RecvVarNames SignalR success!";
                    InvokeAsync(StateHasChanged);
                });

                await hubConnection.SendAsync("GetVarNames");
            }
            catch (Exception e)
            {
                sMsg = e.Message;
            }

            // 获取装备列表
            await GetEquipInfoAsync();
        }

        /// <summary>
        /// 获取所有逻辑表达式
        /// </summary>
        /// <returns></returns>
        private async Task SignalServer(RequestParameter parameter)
        {
            try
            {
                if (hubConnection == null || hubConnection.State == HubConnectionState.Disconnected)
                {
                    // 建立SIGNALR连接
                    hubConnection = new HubConnectionBuilder()
                        .WithUrl("http://127.0.0.1:5000/logichub")
                        .WithAutomaticReconnect([TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(3)])
                        .Build();

                    await hubConnection.StartAsync();
                }

                // 发送请求
                hubConnection.On<IEnumerable<LogicDto>, int, int>("ReceivePagedLogics",
                    (result, curPage, totalPages) =>
                {
                    logicDtos = result;
                    foreach (var item in logicDtos)
                    {
                        if (!dictChanges.ContainsKey(item.Id))
                        {
                            dictChanges.TryAdd(item.Id, true);
                        }
                    }
                    pageParms.PageNumber = curPage;
                    MaxPageNumber = totalPages;
                    sMsg = $"{DateTime.Now} ReceivePagedLogics SignalR success!";
                    InvokeAsync(StateHasChanged);
                });

                await hubConnection.SendAsync("GetPagedLogics", parameter);
            }
            catch (Exception ex)
            {
                sMsg = ex.ToString();
            }
        }

        /// <summary>
        /// 切换到编辑状态
        /// </summary>
        /// <param name="id">逻辑表达式的ID号</param>
        /// <returns></returns>
        private async Task OnSwitchToChanged(int id)
        {
            if (dictChanges.ContainsKey(id))
            {
                dictChanges[id] = false;
                await GetEquipInfoAsync();
            }
        }

        /// <summary>
        /// 保存编辑内容
        /// </summary>
        /// <param name="dto">逻辑表达式视图</param>
        /// <returns></returns>
        private async Task OnAcceptChanged(LogicDto dto)
        {
            if (dictChanges.ContainsKey(dto.Id))
            {
                hubConnection.On<ApiResult<LogicDto>>("RecvUpdateLogic", (content) =>
                {
                    sMsg = $"{DateTime.Now} RecvUpdateLogic Singal Request";
                    InvokeAsync(async () =>
                    {
                        if (content.Success)
                        {
                            dictChanges[dto.Id] = true;
                            await ToastService.Success("通道列表", "更新成功");
                            await SignalServer(pageParms);
                        }
                        else
                        {
                            await ToastService.Error("通道列表", content.Message);
                        }
                    });
                });

                await hubConnection.SendAsync("UpdateLogicAsync", dto);
            }
        }

        /// <summary>
        /// 取消编辑内容
        /// </summary>
        /// <param name="dto">逻辑表达式视图</param>
        /// <returns></returns>
        private async Task OnRefuseChanged(LogicDto dto)
        {
            if (dictChanges.ContainsKey(dto.Id))
            {
                await SignalServer(pageParms);

                dictChanges[dto.Id] = true;
                StateHasChanged();
            }
        }

        /// <summary>
        /// 获取装备列表
        /// </summary>
        /// <returns></returns>
        private async Task GetEquipInfoAsync()
        {
            try
            {
                if (hubConnection.State == HubConnectionState.Connected)
                {
                    hubConnection.On<IEnumerable<EquipDto>>("RecvEquips", (content) =>
                    {
                        sMsg = $"{DateTime.Now} RecvEquips Singal Request";
                        equipList = content.Select(c => new SelectedItem(c.Id.ToString(), c.Name)).ToList();
                        InvokeAsync(StateHasChanged);
                    });

                    await hubConnection.SendAsync("GetEquipsAsync");
                }
            }
            catch (Exception ex)
            {
                await ToastService.Error("逻辑列表", ex.Message);
            }
        }

        /// <summary>
        /// 切换到插入模式
        /// </summary>
        /// <returns></returns>
        private async Task OnSwitchToInsert()
        {
            var calcateFormula = "";
            if (NameItems.Any())
            {
                var name = NameItems.FirstOrDefault()?.Text ?? "";
                var names = name.Split(":");
                calcateFormula = names[0];
                if (names.Length > 1)
                {
                    var c = names[1].Trim()[0];
                    calcateFormula += c switch
                    {
                        'B' => " = true; ",
                        'I' => " = 10; ",
                        'D' => " = 10; ",
                        'S' => " =  \"String\"; ",
                        _ => "",
                    };
                }
            }

            hubConnection.On<int>("RecvMaxId", (maxId) =>
            {
                sMsg = $"{DateTime.Now} RecvMaxId Singal Request";
                addedLogic = new LogicDto
                {
                    Name = "Loop" + (maxId + 1),
                    Description = "新建逻辑表达式",
                    equipId = int.Parse(equipList.FirstOrDefault()?.Value ?? "1"),
                    Enabled = true,
                    ConditionFormula = "true",
                    ClacateFormula = calcateFormula,
                };
                bInsertFlag = true;
                InvokeAsync(StateHasChanged);
            });
            await hubConnection.SendAsync("GetMaxId");
        }

        /// <summary>
        /// 保存插入的逻辑表达式
        /// </summary>
        /// <returns></returns>
        private async Task OnAcceptInsert()
        {
            hubConnection.On<ApiResult<LogicDto>>("RecvInsertLogic", (content) =>
            {
                sMsg = $"{DateTime.Now} RecvInsertLogic Singal Request";
                InvokeAsync(async () =>
                {
                    if (content.Success)
                    {
                        bInsertFlag = false;
                        await ToastService.Success("逻辑表达式", "添加成功");
                    }
                    else
                    {
                        await ToastService.Error("逻辑表达式", content.Message);
                    }
                    await SignalServer(pageParms);
                });
            });

            await hubConnection.SendAsync("InsertLogicAsync", addedLogic);
        }

        /// <summary>
        /// 取消插入的逻辑表达式
        /// </summary>
        /// <returns></returns>
        private Task OnRefuseInsert()
        {
            bInsertFlag = false;
            StateHasChanged();
            return Task.CompletedTask;
        }

        /// <summary>
        /// 删除逻辑表达式
        /// </summary>
        /// <param name="id">逻辑表达式ID号</param>
        /// <returns></returns>
        private async Task OnDeleteLogic(int id)
        {
            if (dictChanges.ContainsKey(id))
            {

                hubConnection.On<ApiResult<LogicDto>>("RecvDeleteLogic", (content) =>
                {
                    sMsg = $"{DateTime.Now} RecvDeleteLogic Singal Request";
                    InvokeAsync(async () =>
                    {
                        if (content.Success)
                        {
                            dictChanges.Remove(id, out _);
                            await ToastService.Success("逻辑表达式", "删除成功");
                            await SignalServer(pageParms);
                        }
                        else
                        {
                            await ToastService.Error("逻辑表达式", content.Message);
                        }
                    });
                });
                await hubConnection.SendAsync("DeleteLogicAsync", id);
            }
        }

        // ---------------------------------------------------------------------------

        /// <summary>
        /// 将下拉列表中的选择结果插入到条件表达式中
        /// </summary>
        /// <param name="item">列表选择项</param>
        /// <param name="id">逻辑表达式ID号</param>
        /// <returns></returns>
        private async Task OnCondRegNameChanged(SelectedItem item, int id)
        {
            var regName = " " + item.Text.Split(':')[0] + " ";
            LogicDto entity = null;
            if (id == 0) entity = addedLogic;
            else entity = logicDtos.FirstOrDefault(c => c.Id == id);

            if (entity == null)
                return;

            if (currentId == id)
            {
                entity.ConditionFormula = HandleStringInsert(entity.ConditionFormula, condCursorStart, condCursorEnd, regName);
                condCursorStart += regName.Length;
                condCursorEnd = condCursorStart;
            }
            else
            {
                entity.ConditionFormula += regName;
            }
            StateHasChanged();
        }

        /// <summary>
        /// 将下拉列表中的选择结果插入到逻辑表达式中
        /// </summary>
        /// <param name="item">列表选择项</param>
        /// <param name="id">逻辑表达式ID号</param>
        /// <returns></returns>
        private  async Task OnClacRegNameChanged(SelectedItem item, int id)
        {
            var regName = item.Text.Split(':')[0];
            LogicDto entity = null;

            if (id == 0) entity = addedLogic;
            else entity = logicDtos.FirstOrDefault(c => c.Id == id);

            if (entity == null)
                return;

            if (currentId == id)
            {
                entity.ClacateFormula = HandleStringInsert(entity.ClacateFormula, calcCursorStart, calcCursorEnd, regName);
                calcCursorStart += regName.Length;
                calcCursorEnd = calcCursorStart;
            }
            else
            {
                entity.ClacateFormula += regName;
            }
            StateHasChanged();
        }


        // ---------------------------------------------------------------------------
        /// <summary>
        /// 翻页响应函数
        /// </summary>
        /// <param name="n">页号</param>
        private async Task OnPageClick(int n)
        {
            pageParms.PageNumber = n;
            await SignalServer(pageParms);
        }

        /// <summary>
        /// 分页数量修改响应
        /// </summary>
        /// <param name="item">每页行数</param>
        private async Task OnPageItemsChanged(SelectedItem item)
        {
            pageParms.PageSize = int.Parse(item.Value);
            pageParms.PageNumber = 1;
            await SignalServer(pageParms);
        }


        [Inject]
        private IJSRuntime JSRuntime { get; set; } = default!;
        private int condCursorStart = 0;
        private int condCursorEnd = 0;
        private int calcCursorStart = 0;
        private int calcCursorEnd = 0;
        private int currentId = 0;

        private async Task OnCondClick(int id)
        {
            condCursorStart = await JSRuntime.InvokeAsync<int>(
                "eval",
                $"document.getElementById('cond{id}').selectionStart");

            condCursorEnd = await JSRuntime.InvokeAsync<int>(
                    "eval",
                    $"document.getElementById('cond{id}').selectionEnd");
            currentId = id;
            Console.WriteLine($"condCursorStart: {condCursorStart}, condCursorEnd: {condCursorEnd}");
        }

        private async Task OnCalcClick(int id)
        {
            calcCursorStart = await JSRuntime.InvokeAsync<int>(
                "eval",
                $"document.getElementById('calc{id}').selectionStart");

            calcCursorEnd = await JSRuntime.InvokeAsync<int>(
                "eval",
                $"document.getElementById('calc{id}').selectionEnd");
            currentId = id;
            Console.WriteLine($"calcCursorStart: {calcCursorStart}, calcCursorEnd: {calcCursorEnd}");
        }

        /// <summary>
        /// 将regName插入到字符串中
        /// </summary>
        /// <param name="source">目标字符串</param>
        /// <param name="start">起始位置</param>
        /// <param name="end">结束位置</param>
        /// <param name="s">插入的字符串</param>
        /// <returns></returns>
        private string HandleStringInsert(string source, int start, int end, string s)
        {
            var sourceLength = source.Length;
            if (start < 0 || start >= sourceLength)
            {
                start = sourceLength == 0 ? 0 : sourceLength;
            }
            if (end < 0 || end >= sourceLength)
            {
                end = sourceLength == 0 ? 0 : sourceLength;
            }
            var sb = new StringBuilder(source);
            sb.Remove(start, end - start);
            sb.Insert(start, s);
            return sb.ToString();
        }
    }
}
